#ifndef _SYS_BUF_H_
#define _SYS_BUF_H_

#include "FanObj.h"
#include "SysTypes.h"

#define BUF_VTABLE(self)   ((BufVTable*)((FanObj*)self)->vtable)


extern Type*    Buf_classType;
extern VTable*  Buf_classVTable;


/* [sys::Buf] Attributes */
struct Buf
{
  FanObj        super;
  OutStream*    out;
  InStream*     in;
};


/* [sys::Buf] Virtual-table */
typedef struct BufVTable
{
  FanObjVTable  super;

  /* Internal virtual methods */
  uint8_t      (*getByte)(Buf* self, Int pos);
  void         (*getBytes)(Buf* self, Int pos, uint8_t* dst, Int len);
  void         (*setByte)(Buf* self, Int pos, uint8_t b);
  Int          (*capacity)(Buf* self);
  void         (*setCapacity)(Buf* self, Int val);
  Int          (*pos)(Buf* self);
  void         (*setPos)(Buf* self, Int pos);
  Int          (*size)(Buf* self);
  void         (*setSize)(Buf* self, Int val);
  Str*         (*toBase64)(Buf* self);
  Str*         (*toHex)(Buf* self);
} BufVTable;


/* [sys::Buf] Methods and fields */
Bool            Buf_equals(Obj self, NullableObj that);
Str*            Buf_toStr(Obj self);
Int             Buf_size(Buf* self);
void            Buf_setSize(Buf* self, Int val);
Int             Buf_capacity(Buf* self);
void            Buf_setCapacity(Buf* self, Int val);
Endian*         Buf_endian(Buf* self);
void            Buf_setEndian(Buf* self, Endian* val);
Charset*        Buf_charset(Buf* self);
void            Buf_setCharset(Buf* self, Charset* val);
Buf*            Buf_make_0(void);
Buf*            Buf_make(Int capacity);
Buf*            Buf_random(Int size);
Bool            Buf_isEmpty(Buf* self);
Int             Buf_pos(Buf* self);
Int             Buf_remaining(Buf* self);
Bool            Buf_more(Buf* self);
Buf*            Buf_seek(Buf* self, Int pos);
Buf*            Buf_flip(Buf* self);
Int             Buf_get(Buf* self, Int index);
Buf*            Buf_getRange(Buf* self, Range* range);
Buf*            Buf_dup(Buf* self);
Buf*            Buf_set(Buf* self, Int index, Int byte);
Buf*            Buf_clear(Buf* self);
Buf*            Buf_trim(Buf* self);
Bool            Buf_close(Buf* self);
Buf*            Buf_flush(Buf* self);
Buf*            Buf_fill(Buf* self, Int byte, Int times);
OutStream*      Buf_out(Buf* self);
Buf*            Buf_write(Buf* self, Int byte);
Buf*            Buf_writeBuf_1(Buf* self, Buf* buf);
Buf*            Buf_writeBuf(Buf* self, Buf* buf, Int n);
Buf*            Buf_writeI2(Buf* self, Int n);
Buf*            Buf_writeI4(Buf* self, Int n);
Buf*            Buf_writeI8(Buf* self, Int n);
Buf*            Buf_writeF4(Buf* self, Float r);
Buf*            Buf_writeF8(Buf* self, Float r);
Buf*            Buf_writeDecimal(Buf* self, Decimal* d);
Buf*            Buf_writeBool(Buf* self, Bool b);
Buf*            Buf_writeUtf(Buf* self, Str* s);
Buf*            Buf_writeChar(Buf* self, Int ch);
Buf*            Buf_writeChars_1(Buf* self, Str* str);
Buf*            Buf_writeChars_2(Buf* self, Str* str, Int off);
Buf*            Buf_writeChars(Buf* self, Str* str, Int off, Int len);
Buf*            Buf_print(Buf* self, NullableObj s);
Buf*            Buf_printLine_0(Buf* self);
Buf*            Buf_printLine(Buf* self, NullableObj obj);
Buf*            Buf_writeProps(Buf* self, Map* props);
Buf*            Buf_writeObj_1(Buf* self, NullableObj obj);
Buf*            Buf_writeObj(Buf* self, NullableObj obj, Map* options);
Buf*            Buf_writeXml_1(Buf* self, Str* s);
Buf*            Buf_writeXml(Buf* self, Str* s, Int flags);
InStream*       Buf_in(Buf* self);
NullableInt     Buf_read(Buf* self);
NullableInt     Buf_readBuf(Buf* self, Buf* buf, Int n);
Buf*            Buf_unread(Buf* self, Int b);
Buf*            Buf_readAllBuf(Buf* self);
Buf*            Buf_readBufFully(Buf* self, Buf* buf, Int n);
NullableInt     Buf_peek(Buf* self);
Int             Buf_readU1(Buf* self);
Int             Buf_readS1(Buf* self);
Int             Buf_readU2(Buf* self);
Int             Buf_readS2(Buf* self);
Int             Buf_readU4(Buf* self);
Int             Buf_readS4(Buf* self);
Int             Buf_readS8(Buf* self);
Float           Buf_readF4(Buf* self);
Float           Buf_readF8(Buf* self);
Decimal*        Buf_readDecimal(Buf* self);
Bool            Buf_readBool(Buf* self);
Str*            Buf_readUtf(Buf* self);
NullableInt     Buf_readChar(Buf* self);
Buf*            Buf_unreadChar(Buf* self, Int b);
NullableInt     Buf_peekChar(Buf* self);
Str*            Buf_readChars(Buf* self, Int n);
Str*            Buf_readLine_0(Buf* self);
Str*            Buf_readLine(Buf* self, NullableInt max);
Str*            Buf_readStrToken_0(Buf* self);
Str*            Buf_readStrToken_1(Buf* self, NullableInt max);
Str*            Buf_readStrToken(Buf* self, NullableInt max, Func* c);
List*           Buf_readAllLines(Buf* self);
void            Buf_eachLine(Buf* self, Func* f);
Str*            Buf_readAllStr_0(Buf* self);
Str*            Buf_readAllStr(Buf* self, Bool normalizeNewlines);
Map*            Buf_readProps(Buf* self);
NullableObj     Buf_readObj_0(Buf* self);
NullableObj     Buf_readObj(Buf* self, Map* options);
Str*            Buf_toHex(Buf* self);
Buf*            Buf_fromHex(Str* s);
Str*            Buf_toBase64(Buf* self);
Buf*            Buf_fromBase64(Str* s);
Buf*            Buf_toDigest(Buf* self, Str* algorithm);
Buf*            Buf_hmac(Buf* self, Str* algorithm, Buf* key);


/* [sys::Buf] Type-system functions */
Type*           Buf_initType(void);
VTable*         Buf_initVTable(void);
void            Buf_initStatic(void);


#endif
